package org.hsqldb.index;

import java.io.IOException;

import org.hsqldb.Row;
import org.hsqldb.RowAVLDisk;
import org.hsqldb.RowLinkList;
import org.hsqldb.error.Error;
import org.hsqldb.error.ErrorCode;
import org.hsqldb.persist.PersistentStore;
import org.hsqldb.rowio.RowInputInterface;
import org.hsqldb.rowio.RowOutputInterface;


public class NodeLinkListDisk extends NodeLinkList{
	
	final RowLinkList row;
	int 					preId = NO_POS;
	int 					nextId = NO_POS;
	int 					selfId = NO_POS; //?
	public int              dataId; //?
	public static final int SIZE_IN_BYTE = 2 * 4;
	
	@Override
	public void write(RowOutputInterface out){
		out.writeInt(preId);
		out.writeInt(nextId);
	}
	
	public NodeLinkListDisk(RowLinkList r, RowInputInterface in,
            int id) throws IOException {

		row      = r;
		selfId      = id;
		dataId    = r.getPos();
		preId = in.readInt();
		nextId    = in.readInt();
		
		
	}
	
	public NodeLinkListDisk(RowLinkList r, int id) {
		row   = r;
		selfId   = id;
		dataId = r.getPos();
	}
	
	public void delete() {
	
		nNext = nPre = null;
		preId = nextId = NO_POS;
	
		row.setNodesChanged();
	}
	
	public boolean isInMemory() {
		return row.isInMemory();
	}
	
	public int getPos() {
        return dataId;
    }

	public void setPos(int p){
		dataId = p;
	}
    public Row getRow(PersistentStore store) {

        if (!row.isInMemory()) {
            return (RowLinkList) store.get(this.row, false);
        } else {
            row.updateAccessCount(store.getAccessCount());
        }

        return row;
    }
    @Override
    NodeLinkList setPre(PersistentStore store, NodeLinkList n) {

        NodeLinkListDisk node = this;
        RowLinkList  row  = this.row;

        if (!row.keepInMemory(true)) {
            row  = (RowLinkList) store.get(this.row, true);
            node = (NodeLinkListDisk) row.getNode(selfId);
        }

        if (!row.isInMemory()) {
            row.keepInMemory(false);

            throw Error.runtimeError(ErrorCode.U_S0500, "NodeAVLDisk");
        }

        row.setNodesChanged();

        node.preId = n == null ? NO_POS
                                 : n.getPos();

        if (n != null && !n.isInMemory()) {
            n = findNode(store, n.getPos());
        }

        node.nPre =  (NodeLinkListDisk)n;

        row.keepInMemory(false);

        return node;
    }
    
    @Override
    NodeLinkList setNext(PersistentStore store, NodeLinkList n){
    	NodeLinkListDisk node = this;
        RowLinkList  row  = this.row;

        if (!row.keepInMemory(true)) {
            row  = (RowLinkList) store.get(this.row, true);
            node = (NodeLinkListDisk) row.getNode(selfId);
        }

        if (!row.isInMemory()) {
            row.keepInMemory(false);

            throw Error.runtimeError(ErrorCode.U_S0500, "NodeAVLDisk");
        }

        row.setNodesChanged();

        node.nextId = n == null ? NO_POS
                                 : n.getPos();

        if (n != null && !n.isInMemory()) {
            n = findNode(store, n.getPos());
        }

        node.nNext =  (NodeLinkListDisk)n;

        row.keepInMemory(false);

        return node;
    }

    NodeLinkList getPre(PersistentStore store) {
    	NodeLinkListDisk node = this;
        RowLinkList  row  = this.row;

        if (!row.isInMemory()) {
            row  = (RowLinkList) store.get(this.row, false);
            node = (NodeLinkListDisk) row.getNode(selfId);
        }

        if (node.preId == NO_POS) {
            return null;
        }

        if (node.nPre == null || !node.nPre.isInMemory()) {
            node.nPre         = findNode(store, node.preId);
            node.nPre.nNext = node;
        }

        return node.nPre;
    }
    NodeLinkList getNext(PersistentStore store) {
    	NodeLinkListDisk node = this;
        RowLinkList  row  = this.row;

        if (!row.isInMemory()) {
            row  = (RowLinkList) store.get(this.row, false);
            node = (NodeLinkListDisk) row.getNode(selfId);
        }

        if (node.nextId == NO_POS) {
            return null;
        }

        if (node.nNext == null || !node.nNext.isInMemory()) {
            node.nNext         = findNode(store, node.nextId);
            node.nNext.nPre = node;
        }

        return node.nNext;
    }
    private NodeLinkListDisk findNode(PersistentStore store, int pos) {

    	NodeLinkListDisk ret = null;
        RowLinkList  r   = (RowLinkList) store.get(pos, false);

        if (r != null) {
            ret = (NodeLinkListDisk) r.getNode(selfId);
        }

        return ret;
    }
}
